#pragma once

#include <Atom.h>
#include <Singleton.h>

#define CLASS_NAME_METHOD(type) \
public: \
	static const liba::Atom& StaticClassName() \
	{ \
		static const liba::Atom className(#type); \
		return className; \
	}

#define PHYSICS_NODE_REGISTER(type) \
	CLASS_NAME_METHOD(type) \
\
	static Node* StaticCreateObject(World *world) \
	{ \
		return new type(world); \
	}

#define PHYSICS_JOINT_REGISTER(type) \
	CLASS_NAME_METHOD(type) \
\
	static Joint* StaticCreateObject(World *world) \
	{ \
		return new type(world); \
	}

namespace physics
{

class World;

template <class T> class Creator:
	public Singleton <Creator <T> >
{
public:
	typedef T * (*CreationFunc)(World *world);

private:
	typedef std::map <liba::Atom, CreationFunc> CreatorsMap;
	CreatorsMap creators;

public:
	CreationFunc FindCreationFunc(const Atom &typeName)
	{
		typename CreatorsMap::const_iterator it = creators.find(typeName);
		if(it == creators.end())
			return NULL;

		return it->second;
	}

	void Register(const Atom &typeName, CreationFunc createFunc)
	{
		creators[typeName] = createFunc;
	}
};



template <class C, class T> class Registrator
{
protected:
	Registrator()
	{
		Creator <C>::GetInstance()->Register(T::StaticClassName(), T::StaticCreateObject);
	}
};



}